package com.settlement.system.service.impl;

import com.settlement.system.common.enums.AccountStatusEnum;
import com.settlement.system.common.enums.CostAllocationEnum;
import com.settlement.system.common.exception.ServiceException;
import com.settlement.system.common.util.SecurityUtils;
import com.settlement.system.common.util.common.DateUtil;
import com.settlement.system.common.util.common.FasUtil;
import com.settlement.system.common.util.common.SystemUserUtil;
import com.settlement.system.mapper.BaseMapper;
import com.settlement.system.mapper.TblCostAllocationDetailMapper;
import com.settlement.system.mapper.security.userdetails.SysUserDetails;
import com.settlement.system.model.entity.common.CommonPlugIn;
import com.settlement.system.model.entity.common.SystemUser;
import com.settlement.system.model.entity.common.TblCostAllocationDetail;
import com.settlement.system.model.entity.common.TblReceiveRefundEditor;
import com.settlement.system.service.ITblCostAllocationDetailService;
import com.settlement.system.service.ITblReceiveRefundEditorService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * RR-费用分摊表 服务实现类
 *
 * @author xiaochuan
 * @since 2023-01-06
 */
@Slf4j
@Service
public class TblCostAllocationDetailServiceImpl extends BaseServiceImpl implements ITblCostAllocationDetailService {

    @Resource
    private TblCostAllocationDetailMapper tblCostAllocationDetailMapper;

    @Resource
    private ITblReceiveRefundEditorService tblReceiveRefundEditorService;

    /*@Reference(version = "${dubbo.acs.api.version}", timeout = 6000)
    private RrPushNcApi rrPushNcApi;*/

    @Override
    public BaseMapper init() {
        return tblCostAllocationDetailMapper;
    }

    @Override
    public List<TblCostAllocationDetail> selectByParams(TblCostAllocationDetail tblCostAllocationDetail) throws ServiceException {
        try {
            return tblCostAllocationDetailMapper.selectByParams(tblCostAllocationDetail);
        } catch (Exception ex) {
            log.error("selectByParams by tblRrRecordProjectMain happen exception", ex);
            throw new ServiceException("selectByParams by tblRrRecordProjectMain happen exception", ex);
        }
    }

    @Override
    public TblCostAllocationDetail getFoot(Map<String, Object> params) throws ServiceException {
        try {
            return tblCostAllocationDetailMapper.getFoot(params);
        } catch (Exception ex) {
            log.error("获取合计异常", ex);
            throw new ServiceException("获取合计异常", ex);
        }
    }

    @Override
    public List<TblCostAllocationDetail> selectStatusBySummaryId(Map<String, Object> params) throws ServiceException {
        try {
            return tblCostAllocationDetailMapper.selectStatusBySummaryId(params);
        } catch (Exception ex) {
            log.error("selectByParams by tblRrRecordProjectMain happen exception", ex);
            throw new ServiceException("selectByParams by tblRrRecordProjectMain happen exception", ex);
        }
    }

    @Override
    public String selectWeightIdBySummaryId(Map<String, Object> params) throws ServiceException {
        try {
            return tblCostAllocationDetailMapper.selectWeightIdBySummaryId(params);
        } catch (Exception ex) {
            log.error("selectByParams by tblRrRecordProjectMain happen exception", ex);
            throw new ServiceException("selectByParams by tblRrRecordProjectMain happen exception", ex);
        }
    }

    @Override
    public String selectWeightIdById(Map<String, Object> params) throws ServiceException {
        try {
            return tblCostAllocationDetailMapper.selectWeightIdById(params);
        } catch (Exception ex) {
            log.error("selectByParams by tblRrRecordProjectMain happen exception", ex);
            throw new ServiceException("selectByParams by tblRrRecordProjectMain happen exception", ex);
        }
    }

    @Override
    public TblCostAllocationDetail getNcBrandByBrandUnitNo(String brandUnitNo) throws ServiceException {
        try {
            return tblCostAllocationDetailMapper.getNcBrandByBrandUnitNo(brandUnitNo);
        } catch (Exception ex) {
            log.error("getNcBrandByBrandUnitNo exception", ex);
            throw new ServiceException("getNcBrandByBrandUnitNo exception", ex);
        }
    }

    @Override
    public TblCostAllocationDetail getNcBrandByBrandName(String brandName) throws ServiceException {
        try {
            return tblCostAllocationDetailMapper.getNcBrandByBrandName(brandName);
        } catch (Exception ex) {
            log.error("getNcBrandByBrandName exception", ex);
            throw new ServiceException("getNcBrandByBrandName exception", ex);
        }
    }

    @Override
    public TblCostAllocationDetail getNcBrandByBrandNo(String brandNo) throws ServiceException {
        try {
            return tblCostAllocationDetailMapper.getNcBrandByBrandNo(brandNo);
        } catch (Exception ex) {
            log.error("getNcBrandByBrandName exception", ex);
            throw new ServiceException("getNcBrandByBrandName exception", ex);
        }
    }


    @Override
    public String getNcBrandNameByNcBrandNo(String ncBrandNo) throws ServiceException {
        try {
            return tblCostAllocationDetailMapper.getNcBrandNameByNcBrandNo(ncBrandNo);
        } catch (Exception ex) {
            log.error("getNcBrandNameByNcBrandNo exception", ex);
            throw new ServiceException("getNcBrandNameByNcBrandNo exception", ex);
        }
    }


    @Override
    public TblCostAllocationDetail getNcBrandByBrandUnitNameShort(String brandUnitNameShort) throws ServiceException {
        try {
            return tblCostAllocationDetailMapper.getNcBrandByBrandUnitNameShort(brandUnitNameShort);
        } catch (Exception ex) {
            log.error("getNcBrandByBrandUnitNo exception", ex);
            throw new ServiceException("getNcBrandByBrandUnitNo exception", ex);
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public String checkBeforeDelete(Map<String, Object> params) throws ServiceException {

        try {
            String channelNo = (String) params.get("channelNo");
            String createUserName = (String) params.get("createUserName");
            String accountingPeriod = (String) params.get("accountingPeriod");
            if (StringUtils.isEmpty(channelNo) || StringUtils.isEmpty(accountingPeriod)) {
                return "操作删除时，渠道、会计期间 必填！";
            }

            Integer integer = tblCostAllocationDetailMapper.selectCountSummaryIdNotCompletelyDeleted(params);
            if (integer > 0) {
                return "同个[统一汇总ID]的数据必须同时删除，不允许部分删除！";
            }

            List<String> notPermitPushFasStatusList = new ArrayList<>();
            notPermitPushFasStatusList.add(CostAllocationEnum.PushFasStatusEnum.T2_PUSHING.getNo());
            notPermitPushFasStatusList.add(CostAllocationEnum.PushFasStatusEnum.T3_PUSH_COMPLETED.getNo());
            List<String> pushFasStatusList = tblCostAllocationDetailMapper.selectPushFasStatus(params);
            if (!CollectionUtils.isEmpty(pushFasStatusList)) {
                for (String pushFasStatus : pushFasStatusList) {
                    if (notPermitPushFasStatusList.contains(pushFasStatus)) {
                        return "[推送FAS状态]=推送中、或 推送完成 的数据，不允许删除，请校验！";
                    }
                }
            }

            List<String> notPermitAccountStatusList = new ArrayList<>();
            notPermitAccountStatusList.add(AccountStatusEnum.T1_IS_CREATING.getNo());
            notPermitAccountStatusList.add(AccountStatusEnum.T2_HAS_CREATED.getNo());
            List<String> accountStatusList = tblCostAllocationDetailMapper.selectAccountStatus(params);
            if (!CollectionUtils.isEmpty(accountStatusList)) {
                for (String accountStatus : accountStatusList) {
                    if (notPermitAccountStatusList.contains(accountStatus)) {
                        return "[记账状态]=生成凭证中、或 已生成凭证 的数据，不允许删除，请校验！";
                    }
                }
            }

            List<String> createUserList = tblCostAllocationDetailMapper.selectCreateUser(params);
            for (String s : createUserList) {
                if (!createUserName.equals(s)) {
                    return "删除操作人与创建人为同一用户，才能操作删除。";
                }
            }

            tblCostAllocationDetailMapper.updateShareStatusAfterDeleteDetail(params);
            tblCostAllocationDetailMapper.deleteByCondition(params);
            //int i=1/0;

        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            throw new ServiceException("", ex);
        }

        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String checkBeforePushToFas(Map<String, Object> params) throws ServiceException {

        try {
            String updateUser = (String) params.get("updateUser");
            String channelNo = (String) params.get("channelNo");
            String beforeOrAfterTicket = (String) params.get("beforeOrAfterTicket");
            String accountingPeriod = (String) params.get("accountingPeriod");
            if (StringUtils.isEmpty(channelNo)
                    || !(StringUtils.isNotEmpty(beforeOrAfterTicket)
                    && beforeOrAfterTicket.contains(CostAllocationEnum.BeforeOrAfterTicketEnum.BEFORE.getNo())
                    && !beforeOrAfterTicket.contains(CostAllocationEnum.BeforeOrAfterTicketEnum.AFTER.getNo())
            )
                    || StringUtils.isEmpty(accountingPeriod)) {
                return "操作删除时，查询条件 渠道、票前票后=\"票前\"、会计期间 必填！";
            }

            Integer countAll = tblCostAllocationDetailMapper.selectCount(params);
            if (countAll == 0) {
                return "未筛选出进行操作的数据";
            }

            Map<String, Object> params2 = new HashMap<>(params);
            params2.put("notBeforeOrAfterTicket", CostAllocationEnum.BeforeOrAfterTicketEnum.BEFORE.getNo());
            Integer notBeforeOrAfterTicketCount = tblCostAllocationDetailMapper.selectCount(params2);
            if (notBeforeOrAfterTicketCount > 0) {
                //return "推送中、或 推送完成 的数据，不允许删除";
                return "只有[票前票后]=\"票前\"，且[推送FAS状态]=\"未推送\"或\"推送失败\"的明细行，才能操作推送FAS";
            }

            List<String> permitPushFasStatusList = new ArrayList<>();
            permitPushFasStatusList.add(CostAllocationEnum.PushFasStatusEnum.T1_NOT_PUSHED.getNo());
            permitPushFasStatusList.add(CostAllocationEnum.PushFasStatusEnum.T4_PUSH_FAILED.getNo());
            List<String> pushFasStatusList = tblCostAllocationDetailMapper.selectPushFasStatus(params);
            if (!CollectionUtils.isEmpty(pushFasStatusList)) {
                for (String pushFasStatus : pushFasStatusList) {
                    if (!permitPushFasStatusList.contains(pushFasStatus)) {
                        return "只有[票前票后]=\"票前\"，且[推送FAS状态]=\"未推送\"或\"推送失败\"的明细行，才能操作推送FAS";
                    }
                }
            }

            String updateTime = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
            params.put("updateTime", updateTime);

            tblCostAllocationDetailMapper.updatePushFasStatus(CostAllocationEnum.PushFasStatusEnum.T2_PUSHING.getNo(), updateUser, updateTime, params);
            //票前费用推送FAS
            /*rrPushNcApi.pushToFas(params);*/
            //int i=1/0;
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            throw new ServiceException("", ex);
        }

        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String checkBeforeDeleteFromFas(Map<String, Object> params) throws ServiceException {

        try {
            String updateUser = (String) params.get("updateUser");
            String channelNo = (String) params.get("channelNo");
            String beforeOrAfterTicket = (String) params.get("beforeOrAfterTicket");
            String accountingPeriod = (String) params.get("accountingPeriod");
            if (StringUtils.isEmpty(channelNo)
                    || !(StringUtils.isNotEmpty(beforeOrAfterTicket)
                    && beforeOrAfterTicket.contains(CostAllocationEnum.BeforeOrAfterTicketEnum.BEFORE.getNo())
                    && !beforeOrAfterTicket.contains(CostAllocationEnum.BeforeOrAfterTicketEnum.AFTER.getNo())
            )
                    || StringUtils.isEmpty(accountingPeriod)) {
                return "操作删除时，查询条件 渠道、票前票后=\"票前\"、会计期间 必填！";
            }

            Integer countAll = tblCostAllocationDetailMapper.selectCount(params);
            if (countAll == 0) {
                return "未筛选出进行操作的数据";
            }

            Map<String, Object> params2 = new HashMap<>(params);
            params2.put("notBeforeOrAfterTicket", CostAllocationEnum.BeforeOrAfterTicketEnum.BEFORE.getNo());
            Integer notBeforeOrAfterTicketCount = tblCostAllocationDetailMapper.selectCount(params2);
            if (notBeforeOrAfterTicketCount > 0) {
                return "只有[票前票后]=\"票前\"，且[推送FAS状态]=\"推送完成\"的明细行，才能操作 删除FAS票前费用";
            }

            List<String> permitPushFasStatusList = new ArrayList<>();
            permitPushFasStatusList.add(CostAllocationEnum.PushFasStatusEnum.T3_PUSH_COMPLETED.getNo());
            List<String> pushFasStatusList = tblCostAllocationDetailMapper.selectPushFasStatus(params);
            if (!CollectionUtils.isEmpty(pushFasStatusList)) {
                for (String pushFasStatus : pushFasStatusList) {
                    if (!permitPushFasStatusList.contains(pushFasStatus)) {
                        return "只有[票前票后]=\"票前\"，且[推送FAS状态]=\"推送完成\"的明细行，才能操作 删除FAS票前费用";
                    }
                }
            }

            String updateTime = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
            params.put("updateTime", updateTime);

            tblCostAllocationDetailMapper.updatePushFasStatus(CostAllocationEnum.PushFasStatusEnum.T5_DELETING.getNo(), updateUser, updateTime, params);
            //删除FAS票前费用
            /*rrPushNcApi.deleteFromFas(params);*/
            //int i=1/0;
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            throw new ServiceException("", ex);
        }

        return null;
    }

    @Override
    public List<String> selectPushFasStatus(Map<String, Object> params) throws ServiceException {
        return tblCostAllocationDetailMapper.selectPushFasStatus(params);
    }

    @Override
    public List<String> selectAccountStatus(Map<String, Object> params) throws ServiceException {
        return tblCostAllocationDetailMapper.selectAccountStatus(params);
    }

    /**
     * 生成NC凭证
     *
     * @param params
     * @return
     * @throws ServiceException
     */
    @Override
    public String produceNc(Map<String, Object> params) throws ServiceException {
        try {
            // 先找出本账户对应的editNo
            SysUserDetails user = SecurityUtils.getUser();;
            String username = user.getUsername();
            TblReceiveRefundEditor editor = tblReceiveRefundEditorService.getEditorByLoginName(username);

            // 当前用户不是制单人身份，提示"撤销人非制单人，故无法撤销！"
            if (editor == null) {
                return "不得生成凭证，生成人不在制单人配置表中，请维护。";
            }

            List<String> permitAccountStatusList = new ArrayList<>();
            permitAccountStatusList.add(AccountStatusEnum.T0_NOT_CREATED.getNo());
            permitAccountStatusList.add(AccountStatusEnum.T8_PRODUCE_NC_FAILED.getNo());
            List<String> accountStatusList = tblCostAllocationDetailMapper.selectAccountStatus(params);
            if (!CollectionUtils.isEmpty(accountStatusList)) {
                for (String status : accountStatusList) {
                    if (!permitAccountStatusList.contains(status)) {
                        return "[票前票后]=\"票后\",且[记账状态]为“未生成凭证”或“生成凭证失败”的 才可操作[生成凭证]";
                    }
                }
            }

            List<String> permitBeforeOrAfterTicketList = new ArrayList<>();
            permitBeforeOrAfterTicketList.add(CostAllocationEnum.BeforeOrAfterTicketEnum.AFTER.getNo());
            List<String> beforeOrAfterTicketList = tblCostAllocationDetailMapper.selectBeforeOrAfterTicket(params);
            if (!CollectionUtils.isEmpty(beforeOrAfterTicketList)) {
                for (String status : beforeOrAfterTicketList) {
                    if (!permitBeforeOrAfterTicketList.contains(status)) {
                        return "[票前票后]=\"票后\",且[记账状态]为“未生成凭证”或“生成凭证失败”的 才可操作[生成凭证]";
                    }
                }
            }

            Integer countAll = tblCostAllocationDetailMapper.selectCount(params);
            if (countAll == 0) {
                return "没有筛选到数据";
            }

            Map tempParams = new HashMap();
            tempParams.putAll(params);
            tempParams.put("accountStatus", AccountStatusEnum.T0_NOT_CREATED.getNo() + "," + AccountStatusEnum.T8_PRODUCE_NC_FAILED.getNo());
            tempParams.put("beforeOrAfterTicket", CostAllocationEnum.BeforeOrAfterTicketEnum.AFTER.getNo());
            FasUtil.formatInQueryCondition(tempParams, "accountStatus");
            String updateTime = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
            // 汇总时，包括不参与记账的，生成凭证时，只处理参与记账的
            tblCostAllocationDetailMapper.updateAccountStatus(AccountStatusEnum.T1_IS_CREATING.getNo(), user.getUsername(), updateTime, tempParams);
            params.put("shareOrNot", CostAllocationEnum.ShareOrNotEnum.YES.getNo());
            params.put("updateUser", username);
            params.put("updateTime", updateTime);
            params.put("accountStatus", AccountStatusEnum.T1_IS_CREATING.getNo());
            /*rrPushNcApi.produceNc(params);*/
        } catch (Exception ex) {
            log.error("生成NC凭证异常", ex);
            throw new ServiceException("生成NC凭证异常", ex);
        }
        return null;
    }

    @Override
    public List<CommonPlugIn> selectExistAccountPeriod() throws ServiceException {
        try {
            return tblCostAllocationDetailMapper.selectExistAccountPeriod();
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            throw new ServiceException("selectExistAccountPeriod exception", ex);
        }
    }
}

